package com.chenhs.oop.study.反射;

import com.chenhs.oop.study.自定义注解.MyAnnotation;
import org.junit.Test;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * <ul>peanut 测试类
 * <li> Author:      chenhs</li>
 * <li>E-Mail:    </li>
 * <li> Date:     2021/6/5 - 14:16</li>
 * <li>Description:        注释  </li>
 * <li>+-History-------------------------------------+</li>
 * <li>| Date          Author       Description    </li>
 * <li>|2021/6/5 - 14:16         chenhs       Created   </li>
 * <li>+------------------------------------------------</li>
 * </ul>
 */
public class MyTest {
	/**
	 *
	 * @Description  获取类的方式
	 * @author chenhs
	 * @Date 2021/6/5
	 * @return
	 */
	@Test
	public void test() throws ClassNotFoundException {
		//	获取类对象的三种方式
		//	通过类名获取
		Class<User> userClass = User.class;
		//通过全限定名获取
		Class<?> userClass2 = Class.forName("com.chenhs.oop.study.反射.User");
		User user = new User();
		//通过类对象获取
		Class<? extends User> userClass3 = user.getClass();
		System.out.println(userClass);
		System.out.println(userClass2);
		System.out.println(userClass3);
	}
	/**
	 *
	 * @Description 方法注释
	 *
	 * @author chenhs
	 * @Date 2021/6/5
	 * @return
	 */
	@org.junit.Test
	public void  test2() throws IllegalAccessException, InstantiationException {
		Class<User> userClass = User.class;
		//获取类名称
		String name = userClass.getName();
		//获取类加载器
		ClassLoader classLoader = userClass.getClassLoader();
		//获取父类
		Class<? super User> superclass = userClass.getSuperclass();
		//判断是否为接口
		boolean anInterface = superclass.isInterface();
		//通过class类对象创建一个对象
		User user = userClass.newInstance();
	}
	@Test
	public void test3() throws NoSuchFieldException, IllegalAccessException, InstantiationException {
		Class<User> userClass = User.class;
		//获取类中的所以属性（不包含私有属性）
		Field[] fields = userClass.getFields();
		System.out.println("打印获取类属性（不包私有）：开始--------------------------");
		for (Field field : fields) {
			System.out.println(field.getName());
		}
		System.out.println("打印获取类属性（不包私有）：结束--------------------------");
		
		
		
		Field[] declaredFields = userClass.getDeclaredFields();
		System.out.println("打印获取类属性（包含私有）：开始--------------------------");
		//获取类中的所有属性 （包含私有属性）
		for (Field field : declaredFields) {
			System.out.println(field.getName());
		}
		System.out.println("打印获取类属性（包含私有）：结束--------------------------");
		
	}
	/**
	 *
	 * @Description 类中属性赋值和取值
	 *
	 * @author chenhs
	 */
	@Test
	public void  test4() throws IllegalAccessException, InstantiationException, NoSuchFieldException {
		Class<User> userClass = User.class;
		User user = userClass.newInstance();
		//通过名称获取指定的属性，如果熟悉是私有的，则无法赋值。
		Field name = userClass.getDeclaredField("name");
		//设置设置属性为可赋值的，就可可以给似有属性赋值。
		name.setAccessible(true);
		name.set(user,"张三");
		//属性获取对中这个属性所存储的值
		System.out.println(name.get(user));
		//获取属性的数据类型
		Class<?> type = name.getType();
		
	}
	/**
	 *
	 * @Description 方法相关
	 *
	 * @author chenhs
	 * @Date 2021/6/5
	 */
	@Test
	public void testMorthed() throws NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
		Class<User> aClass = User.class;
		User user = aClass.newInstance();
		user.setName("张三");
		
		//获取所有方法
		Method[] declaredMethods = aClass.getDeclaredMethods();
		for (Method method : declaredMethods) {
			System.out.println(method.getName());
		}
		//getDeclaredMethod("方法名",参数的类class);,如果不存参数类型的类，那么在方法重载的情况下，会获取到无参的那个方法。
		//当一个方法存在多个参数时用逗号隔开。
		Method speak = aClass.getDeclaredMethod("speak", String.class);
		//调用方法。
		speak.invoke(user,"你的节操碎了");
		//获取参数类型。
		Class<?>[] parameterTypes = speak.getParameterTypes();
		//获取方法发的名称。
		String name = speak.getName();
		//获取返回值类型
		Class<?> returnType = speak.getReturnType();
		
		
	}
	@Test
	public void testConstructor() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
		Class<?> aClass = Class.forName("com.chenhs.oop.study.反射.User");
		//获取构造器 （括号中填写的是构造器的参数列表的参数类型的class）
		Constructor<?> constructor = aClass.getConstructor(String.class, Integer.class);
		User user = (User)constructor.newInstance("张三", 11);
		Field name = aClass.getDeclaredField("name");
		name.setAccessible(true);
		System.out.println(name.get(user));
	}
	/**
	 *
	 * @Description 获取注解
	 *
	 * @author chenhs
	 * @Date 2021/6/5
	 * @return
	 */
	@Test
	public void testNote() throws NoSuchMethodException {
		
		Class<User> userClass = User.class;
		//获取所有注解
		Annotation[] annotations = userClass.getAnnotations();
		for (Annotation annotation : annotations) {
			System.out.println(annotation.getClass().getName());
		}
		//获取指定注解 MyAnnotation.class注解类
		MyAnnotation annotation = userClass.getAnnotation(MyAnnotation.class);
		System.out.println(annotation);
		Method speak = userClass.getMethod("speak", String.class);
		//获取方法上的注解
		System.out.println("-------------------获取方法上的注解-------------");
		MyAnnotation annotation2 = speak.getAnnotation(MyAnnotation.class);
		System.out.println(annotation2);
		
	}
	
}
